<template>
  <div ref="appRef">
    <header>
		<h1><a href="/">glTF Viewer</a></h1>
	</header>
	<main class="wrap">
		<div class="dropzone" ref="dropEl">
			<div class="placeholder">
				<p>拖动 glTF 2.0 文件或文件夹到这里</p>
			</div>
			<div class="upload-btn">
				<input type="file" name="file-input[]" id="file-input" multiple=""  ref="inputEl"/>
				<label for="file-input">
					<svg
						xmlns="http://www.w3.org/2000/svg"
						width="20"
						height="17"
						viewBox="0 0 20 17"
					>
						<path
							d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"
						></path>
					</svg>
					<span>选择文件</span>
				</label>
			</div>
		</div>
		<div class="spinner" ref="spinnerEl"></div>
	</main>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import { Viewer } from "./viewer.js";
import { SimpleDropzone } from "simple-dropzone";
import { Validator } from "./validator.js";
import queryString from "query-string";
import WebGL from "three/addons/capabilities/WebGL.js";

const spinnerEl = ref(null);
const dropEl = ref(null);
const inputEl = ref(null);
const appRef = ref(null);
var validator = ref(null);
let viewer = null;
let viewerEl = null;
const options = ref({
  kiosk: false,
  model: "",
  preset: "",
  cameraPosition: null
});

const createDropzone = () => {
  const dropCtrl = new SimpleDropzone(dropEl.value, inputEl.value);
  dropCtrl.on("drop", ({ files }) => load(files));
  dropCtrl.on("dropstart", () => showSpinner());
  dropCtrl.on("droperror", () => hideSpinner());
};

const createViewer = () => {
  viewerEl = document.createElement("div");
  viewerEl.classList.add("viewer");
  dropEl.value.innerHTML = "";
  dropEl.value.appendChild(viewerEl);
  viewer = new Viewer(viewerEl, options.value);
  return viewer;
};

const load = fileMap => {
  let rootFile;
  let rootPath;
  Array.from(fileMap).forEach(([path, file]) => {
    if (file.name.match(/\.(gltf|glb)$/)) {
      rootFile = file;
      rootPath = path.replace(file.name, "");
    }
  });

  if (!rootFile) {
    onError("No .gltf or .glb asset found.");
  }

  view(rootFile, rootPath, fileMap);
};

const view = (rootFile, rootPath, fileMap) => {
  if (viewer) viewer.clear();

  const viewerInstance = viewer || createViewer();
  const fileURL =
    typeof rootFile === "string" ? rootFile : URL.createObjectURL(rootFile);

  const cleanup = () => {
    hideSpinner();
    if (typeof rootFile === "object") URL.revokeObjectURL(fileURL);
  };
 console.log(viewerInstance,"viewerInstance")
  viewerInstance
    .load(fileURL, rootPath, fileMap)
    .catch(onError)
    .then(gltf => {
      if (!options.value.kiosk) {
        validator.value.validate(fileURL, rootPath, fileMap, gltf);
      }
      cleanup();
    });
};

const onError = error => {
  let message = (error || {}).message || error.toString();
  if (message.match(/ProgressEvent/)) {
    message =
      "Unable to retrieve this file. Check JS console and browser network tab.";
  } else if (message.match(/Unexpected token/)) {
    message = `Unable to parse file content. Verify that this file is valid. Error: "${message}"`;
  } else if (error && error.target && error.target instanceof Image) {
    message = "Missing texture: " + error.target.src.split("/").pop();
  }
  window.alert(message);
  console.error(error);
};

const showSpinner = () => {
  spinnerEl.value.style.display = "";
};

const hideSpinner = () => {
  spinnerEl.value.style.display = "none";
};
onMounted(() => {
  console.log(appRef.value,"validator")
validator.value = new Validator(appRef.value);
  const hash = location.hash ? queryString.parse(location.hash) : {};
  options.value = {
    kiosk: Boolean(hash.kiosk),
    model: hash.model || "",
    preset: hash.preset || "",
    cameraPosition: hash.cameraPosition
      ? hash.cameraPosition.split(",").map(Number)
      : null
  };

  if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
    console.error("The File APIs are not fully supported in this browser.");
  } else if (!WebGL.isWebGLAvailable()) {
    console.error("WebGL is not supported in this browser.");
  }

  createDropzone();

  if (options.value.kiosk) {
    const headerEl = document.querySelector("header");
    headerEl.style.display = "none";
  }

  if (options.value.model) {
    view(options.value.model, "", new Map());
  }

  window.VIEWER = { app: this };

  console.info("[glTF Viewer] Debugging data exported as `window.VIEWER`.");
});
</script>

<style scoped>

.wrap {
  display: flex;
  width: 100vw;
  height: 93vh;
  flex-grow: 1;
  position: relative;
}

.dropzone {
  display: flex;
  flex-grow: 1;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.placeholder {
  width: 100%;
  max-width: 500px;
  border-radius: 0.5em;
  background: #252525;
  padding: 2em;
  text-align: center;
}

.placeholder p {
  font-size: 1.2rem;
  color: #999;
}

.viewer {
  width: 93vw;
  height: 100vh;
  flex-grow: 1;
  flex-shrink: 1;
  position: absolute;
  top: 0;
  z-index: 0;
}

.axes {
    width: 100px;
    height: 100px;
    margin: 20px;
    padding: 0px;
    position: absolute;
    left: 0px;
    bottom: 0px;
    z-index: 10;
    pointer-events: none;
}

/******************************************************************************
 * Header
 */

header {
  display: flex;
  background: #353535;
  padding: 0 2em;
  height: 7vh;
  line-height: 4rem;
  align-items: center;
  overflow-x: auto;
  overflow-y: hidden;
  white-space: nowrap;
  box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, 0.3);
  z-index: 1;

  -webkit-app-region: drag;
}

header h1 {
  color: #F5F5F5;
  font-size: 1.4rem;
  font-weight: 300;
  line-height: 4rem;
  margin: 0;
}

header h1 > a {
  color: inherit;
  font-size: inherit;
  text-decoration: inherit;
}

/* .gui-wrap {
  position: fixed !important;
  top: 7.5vh;
  right: 0.5vw;
  pointer-events: none;
}

.gui-wrap > .main {
  pointer-events: all;
  max-height: 100%;
  overflow: auto;
} */

.dg li.gui-stats:not(.folder) {
  height: auto;
}

@media screen and (max-width: 700px) {
  header h1 {
    font-size: 1em;
  }
}

/******************************************************************************
 * Footer
 */

footer {
  position: absolute;
  bottom: 0.5em;
  right: 0.5em;
  font-family: monospace;
  color: #fff;
}

footer a {
  color: inherit;
  opacity: 0.5;
  text-decoration: inherit;
}

footer a:hover {
  opacity: 1;
  text-decoration: underline;
}

footer .separator {
  margin: 0 0.5em;
  opacity: 0.2;
}

/******************************************************************************
 * Upload Button
 *
 * https://tympanus.net/Tutorials/CustomFileInputs/
 */

.upload-btn {
  margin-top: 2em;
}

.upload-btn input {
  width: 0.1px;
  height: 0.1px;
  opacity: 0;
  overflow: hidden;
  position: absolute;
  z-index: -1;
}

.upload-btn label {
  color: #808080;
  border: 0;
  border-radius: 3px;
  transition: ease 0.2s background;
  font-size: 1rem;
  font-weight: 700;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
  display: inline-block;
  overflow: hidden;
  padding: 0.625rem 1.25rem;
}

.upload-btn label:hover {
  background: #252525;
}

.upload-btn svg {
  width: 1em;
  height: 1em;
  vertical-align: middle;
  fill: currentColor;
  margin-top: -0.25em;
  margin-right: 0.25em;
}


/******************************************************************************
 * Validation report
 */

.report {
  padding: 2em;
  max-width: 860px;
}

.report h1 {
  margin-top: 0;
}

.report p,
.report ul {
  line-height: 1.5em;
}

.report-table {
  text-align: left;
  border-collapse: collapse;
  width: 100%;
}

.report-table thead tr {
  background: #404040;
  color: #FFF;
}

.report-table th,
.report-table td {
  padding: 0.5em 1em;
}

.report-table tr:nth-child(2n) {
  background: #F0F0F0;
}

/******************************************************************************
 * Validation toggle
 */

.report-toggle-wrap.hidden { display: none; }

.report-toggle {
  cursor: pointer;
  display: flex;
  position: absolute;
  bottom: 0;
  left: 20px;
  height: 30px;
  box-shadow: 0px 0px 5px 0 rgba(0, 0, 0, 0.25);
  background: #FFF;
  box-sizing: border-box;

  color: #f0f0f0;
  background: #000;
  border-left: 6px solid #000;
}

.report-toggle.level-1 { color: #444; background: #ffeda0; border-left-color: #feb24c; }
.report-toggle.level-0 { color: #444; background: #f4c2be; border-left-color: #b10026; }

.report-toggle-text {
  line-height: 32px;
  padding: 0 0.5em;
  font-weight: 300;
  font-size: 0.8em;
}

.report-toggle-close {
  width: 30px;
  height: 30px;
  line-height: 30px;
  font-size: 1.5em;
  text-align: center;
}

/******************************************************************************
 * CSS Spinner
 *
 * http://tobiasahlin.com/spinkit/
 */

.spinner {
  width: 40px;
  height: 40px;
  position: absolute;
  left: 50%;
  top: 50%;
  margin: -20px;

  background-color: #333;

  border-radius: 100%;
  -webkit-animation: sk-scaleout 1.0s infinite ease-in-out;
  animation: sk-scaleout 1.0s infinite ease-in-out;
}

@-webkit-keyframes sk-scaleout {
  0% { -webkit-transform: scale(0) }
  100% {
    -webkit-transform: scale(1.0);
    opacity: 0;
  }
}

@keyframes sk-scaleout {
  0% {
    -webkit-transform: scale(0);
    transform: scale(0);
  } 100% {
    -webkit-transform: scale(1.0);
    transform: scale(1.0);
    opacity: 0;
  }
}

</style>